[模板]Treap

2020-01-19
模板

题意

维护一个数据结构,支持插入;删除;查询某个数的排名;查询排名为x的数;查询前驱;查询后继

题解

Treap,结合二叉搜索树和堆

按照随机权值以堆的形式排列,保证复杂度

调试记录

暂无

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <cstdio>
#include <cstdlib>
#include <algorithm>
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
struct T{
#define S(d) a[a[cur].son[d]]
struct A{
int son[2], v, sz, lnk, rd;
}a[maxn << 1]; int tot;
T(){tot = 0;}
void pushup(int cur){
a[cur].sz = S(0).sz + S(1).sz + a[cur].v;
}
void rotate(int &cur, int d){
int k = a[cur].son[d ^ 1];
a[cur].son[d ^ 1] = a[k].son[d];
a[k].son[d] = cur;
pushup(cur); pushup(k);
cur = k;
}
void ins(int &cur, int x){
if (!cur){
cur = ++tot;
a[cur].sz = a[cur].v = 1;
a[cur].lnk = x;
a[cur].rd = rand();
return;
}
if (a[cur].lnk == x){
a[cur].v++; a[cur].sz++;
return;
}
int d = (x > a[cur].lnk);
ins(a[cur].son[d], x);
if (a[cur].rd < S(d).rd) rotate(cur, d ^ 1);
pushup(cur);
}
void del(int &cur, int x){
if (!cur) return;
if (x < a[cur].lnk) del(a[cur].son[0], x);
else if (x > a[cur].lnk) del(a[cur].son[1], x);
else{
if (a[cur].v > 1){
a[cur].v--;
a[cur].sz--;
}
else if (!a[cur].son[0] && !a[cur].son[1]){
a[cur].sz--;
if (--a[cur].v == 0) cur = 0;
}
else if (a[cur].son[0] && !a[cur].son[1]){
rotate(cur, 1);
del(a[cur].son[1], x);
}
else if (!a[cur].son[0] && a[cur].son[1]){
rotate(cur, 0);
del(a[cur].son[0], x);
}
else{
int d = (S(0).rd > S(1).rd);
rotate(cur, d);
del(a[cur].son[d], x);
}
}
pushup(cur);
}
int rank(int cur, int x){
if (!cur) return 0;
if (a[cur].lnk == x) return S(0).sz + 1;
if (a[cur].lnk < x) return S(0).sz + a[cur].v + rank(a[cur].son[1], x);
if (a[cur].lnk > x) return rank(a[cur].son[0], x);
}
int find(int cur, int x){
if (!cur) return 0;
if (S(0).sz >= x) return find(a[cur].son[0], x);
else if (S(0).sz + a[cur].v >= x) return a[cur].lnk;
else return find(a[cur].son[1], x - S(0).sz - a[cur].v);
}
int pre(int cur, int x){
if (!cur) return -INF;
if (a[cur].lnk >= x) return pre(a[cur].son[0], x);
return max(a[cur].lnk, pre(a[cur].son[1], x));
}
int suf(int cur, int x){
if (!cur) return INF;
if (a[cur].lnk <= x) return suf(a[cur].son[1], x);
return min(a[cur].lnk, suf(a[cur].son[0], x));
}
}t; int Q, rt;
int main(){
scanf("%d", &Q);
while (Q--){
int opt, x;
scanf("%d%d", &opt, &x);
if (opt == 1) t.ins(rt, x);
if (opt == 2) t.del(rt, x);
if (opt == 3) printf("%d\n", t.rank(rt, x));
if (opt == 4) printf("%d\n", t.find(rt, x));
if (opt == 5) printf("%d\n", t.pre(rt, x));
if (opt == 6) printf("%d\n", t.suf(rt, x));
}
return 0;
}